package com.lijinjiang.view;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.printing.PDFPrintable;
import org.apache.pdfbox.printing.Scaling;

import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.Attribute;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.Sides;
import javax.swing.*;
import java.awt.*;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

/**
 * @Location
 * @Description 打印界面
 * @Author 03010430
 * @ModifyDate 2022/11/23 17:18
 */
public class PrintFrame {
    private String filepath;//文件路径
    private HashMap<String, PrintService> serviceMap = null;//打印机列表
    private PrintService defaultPrintService;//默认打印机
    private Integer copies;//打印份数
    private Scaling scaling;//缩放形式
    private int orientation;//页面方向
    private Attribute sides;//单双面打印

    public PrintFrame(String filepath) {
        //打印PDF
        this.filepath = filepath;
        serviceMap = new HashMap<String, PrintService>();//初始化打印机服务器集合
        JFrame frame = new JFrame();
        frame.setSize(new Dimension(430, 300));//设置大小
        frame.setTitle("打印PDF");//设置标题
        JPanel contentPanel = new JPanel();
        contentPanel.setLayout(new GridLayout(6, 1, 10, 2));
        JPanel panel01 = new JPanel(null);
        JLabel label01 = new JLabel("打印机 : ");
        label01.setBounds(10, 10, 100, 32);
        JComboBox<String> serviceComboBox = selectPrintService();
        serviceComboBox.setBounds(100, 10, 270, 30);
        panel01.add(label01);
        panel01.add(serviceComboBox);

        JPanel panel02 = new JPanel(null);
        JLabel label02 = new JLabel("份数 : ");
        label02.setBounds(10, 10, 100, 32);
        JTextField countField = new JTextField(10);
        countField.setBounds(100, 10, 270, 30);
        countField.setText("1");
        panel02.add(label02);
        panel02.add(countField);

        JPanel panel03 = new JPanel(null);
        JLabel label03 = new JLabel("调整页面大小 : ");
        label03.setBounds(10, 10, 95, 32);
        JPanel right03 = new JPanel(new BorderLayout());
        right03.setBounds(88, 8, 330, 30);
        JPanel radioPanel03 = new JPanel();
        JRadioButton fitBtn01 = new JRadioButton("合适");//SCALE_TO_FIT
        fitBtn01.setSelected(true);//默认适合大小
        JRadioButton fitBtn02 = new JRadioButton("实际大小");//ACTUAL_SIZE
        JRadioButton fitBtn03 = new JRadioButton("缩放裁剪");//SHRINK_TO_FIT
        JRadioButton fitBtn04 = new JRadioButton("拉伸适应");//STRETCH_TO_FIT
        ButtonGroup group03 = new ButtonGroup();
        group03.add(fitBtn01);
        group03.add(fitBtn02);
        group03.add(fitBtn03);
        group03.add(fitBtn04);
        panel03.add(label03);
        radioPanel03.add(fitBtn01);
        radioPanel03.add(fitBtn02);
        radioPanel03.add(fitBtn03);
        radioPanel03.add(fitBtn04);
        right03.add(radioPanel03, BorderLayout.WEST);
        panel03.add(right03);

        JPanel panel04 = new JPanel(null);
        JLabel label04 = new JLabel("方向 : ");
        label04.setBounds(10, 10, 95, 32);
        JPanel right04 = new JPanel(new BorderLayout());

        right04.setBounds(88, 8, 330, 30);
        JPanel radioPanel04 = new JPanel();
        JRadioButton orientationBtn01 = new JRadioButton("纵向");//纵向
        orientationBtn01.setSelected(true);//默认纵向
        JRadioButton orientationBtn02 = new JRadioButton("横向");//横向
        ButtonGroup group04 = new ButtonGroup();
        group04.add(orientationBtn01);
        group04.add(orientationBtn02);
        panel04.add(label04);
        radioPanel04.add(orientationBtn01);
        radioPanel04.add(orientationBtn02);
        right04.add(radioPanel04, BorderLayout.WEST);
        panel04.add(right04);

        JPanel panel05 = new JPanel(null);
        JLabel label05 = new JLabel("单双面打印 : ");
        label05.setBounds(10, 10, 95, 32);
        JPanel right05 = new JPanel(new BorderLayout());
        right05.setBounds(88, 8, 330, 30);
        JPanel radioPanel05 = new JPanel();
        JRadioButton sidesBtn01 = new JRadioButton("单面打印");//单面打印
        JRadioButton sidesBtn02 = new JRadioButton("双面打印");//双面打印
        sidesBtn02.setSelected(true);//默认双面打印
        ButtonGroup group05 = new ButtonGroup();
        group05.add(sidesBtn01);
        group05.add(sidesBtn02);
        panel05.add(label05);
        radioPanel05.add(sidesBtn01);
        radioPanel05.add(sidesBtn02);
        right05.add(radioPanel05, BorderLayout.WEST);
        panel05.add(right05);

        JPanel panel06 = new JPanel();
        JButton confirmBtn = new JButton("打印");//确认
        confirmBtn.addActionListener(e -> {
            //获取打印机服务
            String item = serviceComboBox.getSelectedItem().toString();
            defaultPrintService = serviceMap.get(item);
            //打印份数
            String text = countField.getText();
            if (text != null) {
                try {
                    copies = Integer.parseInt(text);
                    if (copies > 99) {
                        System.out.println("打印份数过多，时间可能很长，请使用其他方式打印！");
                        return;
                    }
                } catch (NumberFormatException nfe) {
                    System.out.println("打印份数填写不规范，请确认后重试！");
                    return;
                }
            } else {
                System.out.println("打印份数填写不规范，请确认后重试！");
                return;
            }
            //缩放形式
            if (fitBtn01.isSelected()) {
                scaling = Scaling.SCALE_TO_FIT;//合适大小
            } else if (fitBtn02.isSelected()) {
                scaling = Scaling.ACTUAL_SIZE;
            } else if (fitBtn03.isSelected()) {
                scaling = Scaling.SHRINK_TO_FIT;
            } else if (fitBtn04.isSelected()) {
                scaling = Scaling.STRETCH_TO_FIT;
            }
            //页面方向
            if (orientationBtn01.isSelected()) {
                orientation = PageFormat.PORTRAIT;//竖向
            } else if (orientationBtn02.isSelected()) {
                orientation = PageFormat.LANDSCAPE;//横向
            }
            //单双面打印
            if (sidesBtn01.isSelected()) {
                sides = Sides.ONE_SIDED;//单面打印
            } else if (sidesBtn02.isSelected()) {
                sides = Sides.DUPLEX;//双面打印
            }
            try {
                print(frame);
            } catch (Exception ue) {
                ue.printStackTrace();
            }
        });
        JButton cancelBtn = new JButton("取消");//取消
        cancelBtn.addActionListener(e -> {
            frame.dispose();//点取消关闭窗口
        });

        panel06.add(confirmBtn);
        panel06.add(cancelBtn);

        contentPanel.add(panel01);
        contentPanel.add(panel02);
        contentPanel.add(panel03);
        contentPanel.add(panel04);
        contentPanel.add(panel05);
        contentPanel.add(panel06);
        frame.add(contentPanel);

        frame.setLocationRelativeTo(null);//设置屏幕居中
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);//设置可见
        frame.setResizable(false);//设置大小不可改变
    }

    /**
     * 获取本地的打印服务，并且设置默认打印机
     */
    private JComboBox<String> selectPrintService() {
        defaultPrintService = PrintServiceLookup.lookupDefaultPrintService();//获取默认打印机
        JComboBox<String> comboBox = new JComboBox<>();
        //获得本台电脑连接的所有打印机
        PrintService[] printServices = PrinterJob.lookupPrintServices();
        if (printServices == null || printServices.length == 0) {
            comboBox.addItem("获取本地打印机失败，请联系管理员！");
        } else {
            for (PrintService printService : printServices) {
                String value = printService.getName();
                serviceMap.put(value, printService);//将打印机名称及打印机服务添加到集合
                comboBox.addItem(value);
                //将默认打印机设置为下拉选的默认选择项
                if (defaultPrintService != null && defaultPrintService.getName().equals(value)) {
                    comboBox.setSelectedItem(value);
                }
            }
        }
        return comboBox;
    }

    /**
     * 打印功能实现
     */
    public void print(Container parent) {
        PDDocument document = null;
        File file;
        try {
            file = new File(filepath);
            if (file == null || !file.exists()) {
                JOptionPane.showMessageDialog(parent, "要打印的PDF文件不存在！", "警告", JOptionPane.WARNING_MESSAGE);
                return;
            }
            document = PDDocument.load(file);
            PrinterJob printerJob = PrinterJob.getPrinterJob();
            printerJob.setJobName(file.getName());
            printerJob.setPrintService(defaultPrintService);//设置打印机
            //设置纸张及缩放
            PDFPrintable pdfPrintable = new PDFPrintable(document, scaling);
            //设置多页打印
            Book book = new Book();
            PageFormat pageFormat = new PageFormat();
            //设置打印方向
            pageFormat.setOrientation(orientation);//纵向
            Paper paper = getPaper();
            pageFormat.setPaper(paper);
            book.append(pdfPrintable, pageFormat, document.getNumberOfPages());
            printerJob.setPageable(book);
            printerJob.setCopies(copies);//设置打印份数
            //添加打印属性
            HashPrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
            attributes.add(sides); //设置单双页
            attributes.add(MediaSizeName.ISO_A4);//默认A4纸打印
            printerJob.print(attributes);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (document != null) {
                try {
                    document.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private Paper getPaper() {
        Paper paper = new Paper();
        // 默认为A4纸张，对应像素宽和高分别为 595, 842
        int width = 595;
        int height = 842;
        // 设置边距，单位是像素，10mm边距，对应 28px
        int marginLeft = 12;
        int marginRight = 12;
        int marginTop = 12;
        int marginBottom = 12;
        paper.setSize(width, height);
        // 下面一行代码，解决了打印内容为空的问题
        paper.setImageableArea(marginLeft, marginRight, width - (marginLeft + marginRight), height - (marginTop + marginBottom));
        return paper;
    }
}
